﻿using Microsoft.Office.InfoPath;

namespace InfoPathHelpers.Validation
{
    /// <summary>
    /// Provides a number of methods for validating different data types.
    /// Note: These methods should only be called from a validation event.
    /// </summary>
    public static partial class ValidationHelper
    {
        /// <summary>
        /// Provides validation for maximum length allowed on a string field.
        /// </summary>
        /// <param name="eventArgs">The XmlValidatingEventArgs of the validation event</param>
        /// <param name="maxLength">Specifies the maximum length allowed.</param>
        /// <returns>True if the length was above the maximum; otherwise false.</returns>
        public static bool MaxLength(XmlValidatingEventArgs eventArgs, int maxLength)
        {
            return MaxLength(eventArgs, maxLength, false);
        }

        /// <summary>
        /// Provides validation for maximum length allowed on a string field 
        /// with the option to show dialog to the user for failures.
        /// </summary>
        /// <param name="eventArgs">The XmlValidatingEventArgs of the validation event</param>
        /// <param name="maxLength">Specifies the maximum length allowed.</param>
        /// <param name="showDialog">A boolean value indicating whether or not to show the user a message on validation failure.</param>
        /// <returns>True if the length was above the maximum; otherwise false.</returns>
        public static bool MaxLength(XmlValidatingEventArgs eventArgs, int maxLength, bool showDialog)
        {
            return MaxLength(eventArgs, maxLength, showDialog,
                new ValidationMessage()
                {
                    Caption = "Invalid Entry",
                    Message = "Too many characters entered",
                    MessageDetails = "This field allows only " + maxLength + " characters"
                }
            );
        }

        /// <summary>
        /// Provides validation for maximum length allowed on a string field 
        /// with the option to show a custom dialog to the user for failures.
        /// </summary>
        /// <param name="eventArgs">The XmlValidatingEventArgs of the validation event</param>
        /// <param name="maxLength">Specifies the maximum length allowed.</param>
        /// <param name="showDialog">A boolean value indicating whether or not to show the user a message on validation failure.</param>
        /// <param name="invalidMessage">The message to show for fields exceeding maximum length.</param>
        /// <returns>True if the length was above the maximum; otherwise false.</returns>
        public static bool MaxLength(XmlValidatingEventArgs eventArgs, int maxLength, bool showDialog, ValidationMessage invalidMessage)
        {
            // Delete operations or unspecififed operations are not validated so just return true.
            if (eventArgs.Operation == XmlOperation.Delete || eventArgs.Operation == XmlOperation.None)
                return true;

            // Insert operations do not use the New/OldValue parameters of XmlValidatingEventArgs
            // so we need to use the Value of the underlying xml element.
            string Value = eventArgs.Site.Value;

            if (Value.Length > maxLength)
            {
                // If the length value is greater than the allowed length validation has failed.
                // So we report failure using "invalidMessage".
                HandleValidationFailure(eventArgs, invalidMessage, showDialog);
                // And of course return false because validation failed.
                return false;
            }
            // Otherwise the length must be less so it is valid.
            return true;
        }

        /// <summary>
        /// Provides validation for minimimum length allowed on a string field.
        /// </summary>
        /// <param name="eventArgs">The XmlValidatingEventArgs of the validation event</param>
        /// <param name="minLength">Specifies the minimum length allowed.</param>
        /// <returns>True if the length was above the minimum; otherwise false.</returns>
        public static bool MinLength(XmlValidatingEventArgs eventArgs, int minLength)
        {
            return MinLength(eventArgs, minLength, false, false);
        }

        /// <summary>
        /// Provides validation for minimimum length allowed on a string field 
        /// with the option to show dialog to the user for failures.
        /// </summary>
        /// <param name="eventArgs">The XmlValidatingEventArgs of the validation event</param>
        /// <param name="minLength">Specifies the minimum length allowed.</param>
        /// <param name="allowBlanks">A boolean value indicating whether or not the field can be empty.</param>
        /// <param name="showDialog">A boolean value indicating whether or not to show the user a message on validation failure.</param>
        /// <returns>True if the length was above the minimum; otherwise false.</returns>
        public static bool MinLength(XmlValidatingEventArgs eventArgs, int minLength, bool allowBlanks, bool showDialog)
        {
            return MinLength(eventArgs, minLength, allowBlanks, showDialog,
                new ValidationMessage()
                {
                    Caption = "Invalid Entry",
                    Message = "Too few characters entered",
                    MessageDetails = "This field must contain at least " + minLength + " characters"
                },
                new ValidationMessage()
                {
                    Caption = "Blank Entry",
                    Message = "Cannot be blank.",
                    MessageDetails = "This field must contain a valid date.",
                }
            );
        }

        /// <summary>
        /// Provides validation for minimimum length allowed on a string field
        /// with the option to show a custom dialog to the user for failures.
        /// </summary>
        /// <param name="eventArgs">The XmlValidatingEventArgs of the validation event</param>
        /// <param name="minLength">Specifies the minimum length allowed.</param>
        /// <param name="allowBlanks">A boolean value indicating whether or not the field can be empty.</param>
        /// <param name="showDialog">A boolean value indicating whether or not to show the user a message on validation failure.</param>
        /// <param name="blankMessage">The message to show for blank fields if not allowed.</param>
        /// <param name="invalidMessage">The message to show for fields less than minimum length.</param>
        /// <returns>True if the length was above the minimum; otherwise false.</returns>
        public static bool MinLength(XmlValidatingEventArgs eventArgs, int minLength, bool allowBlanks, bool showDialog, ValidationMessage invalidMessage, ValidationMessage blankMessage)
        {
            // Delete operations or unspecififed operations are not validated so just return true.
            if (eventArgs.Operation == XmlOperation.Delete || eventArgs.Operation == XmlOperation.None)
                return true;

            // Insert operations do not use the New/OldValue parameters of XmlValidatingEventArgs
            // so we need to use the Value of the underlying xml element.
            string Value = eventArgs.Site.Value;

            bool IsEmpty = string.IsNullOrEmpty(Value);
            bool IsAboveMinimumLength = Value.Length >= minLength;

            // If the field is not empty and the value below minimum length then validation has failed.
            if (!IsEmpty && !IsAboveMinimumLength)
            {
                // If the field is not empty and the value is not a valid email address then validation has failed.
                // So we report failure using "invalidMessage".
                HandleValidationFailure(eventArgs, invalidMessage, showDialog);
                // And of course return false because validation failed.
                return false;
            }
            // If the value is empty but validation does not allow blanks then validation fails.
            else if (IsEmpty && !allowBlanks)
            {
                // If the value is empty but validation does not allow blanks then validation fails.
                // So we report failure using the "blankMessage".
                HandleValidationFailure(eventArgs, blankMessage, showDialog);
                // And of course return false because validation failed.
                return false;
            }

            // Otherwise either the field is empty or a valid date so validation succeeded.
            return true;
        }
    }  
}
